package com.azxc.rapid.common.aop;

import com.alibaba.fastjson.JSONObject;
import com.azxc.rapid.common.aop.anno.*;
import com.azxc.rapid.common.utils.DictUtil;
import com.azxc.rapid.plus.user.cache.UserPlusCache;
import com.azxc.rapid.system.cache.RegionCache;
import com.azxc.rapid.system.cache.SysCache;
import com.azxc.rapid.system.entity.Dept;
import com.azxc.rapid.system.entity.Region;
import com.azxc.rapid.system.user.entity.User;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


@Aspect
@Component
@Slf4j
public class TranslationAspect {
	/**
	 * 一次查询多个用户的集合
	 *
	 * @param fieldPattern
	 * @param fieldMatcher
	 */
	public Map<Long, User> getUserMap(Pattern fieldPattern, Matcher fieldMatcher) {
		List<String> ids = new ArrayList<>();
		while (fieldMatcher.find()) {
			//取出要翻译字段对应的值
			Matcher dictValueMatcher = fieldPattern.matcher(fieldMatcher.group());
			dictValueMatcher.find();
			String group = dictValueMatcher.group();
			//属性无值
			if (group.split(":").length <= 1) continue;
			//获取被翻译的值
			String userId = group.split(":")[1].replace("\"", "");
			//属性值非为空 为空赋值空串
			StringBuffer buffer = new StringBuffer();
			if (StringUtils.isNotBlank(userId) && !userId.toLowerCase().equals("null")) {
				ids.add(userId);
			}
		}
		List<User> list = UserPlusCache.getUsers(ids.stream().collect(Collectors.joining(",")));
		Map<Long, User> map = Optional.ofNullable(list).orElse(new ArrayList<>()).stream().collect(Collectors.toMap(User::getId, t -> t));
		return map;
	}

	/**
	 * 获取对应的正则式
	 *
	 * @return
	 */
	public Pattern getPattern(String fileValue, Class clazz) {
		Pattern fieldPattern;//属性整型 字符型
		if (clazz.equals(String.class)) {
			fieldPattern = Pattern.compile("\"" + fileValue + "\":\"([0-9a-zA-Z_,]+)?\"");
		} else {
			fieldPattern = Pattern.compile("\"" + fileValue + "\":(\\d+)?");
		}
		return fieldPattern;
	}

	/**
	 * 翻译字典值
	 *
	 * @param joinPoint
	 * @return
	 * @throws Throwable
	 */
	@Around("@annotation(com.azxc.rapid.common.aop.anno.TranslationDict)")
	public Object aroundMethodDict(ProceedingJoinPoint joinPoint) throws Throwable {
		//接收到请求时间
		Long startTime = System.currentTimeMillis();
		//注意，如果调用joinPoint.proceed()方法，则修改的参数值不会生效，必须调用joinPoint.proceed(Object[] args)
		Object result = joinPoint.proceed();
		// 第一步、获取返回值类型
		Class returnType = ((MethodSignature) joinPoint.getSignature()).getReturnType();
		//首先，取出要翻译字段的字典值
		String returnJsonResult = JSONObject.toJSONString(result);
		//开始解析（翻译字段注解参数指定的字段）
		Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
		//获取注解上参数
		TranslationDict annotation = method.getAnnotation(TranslationDict.class);
		FieldParam[] fieldParams = annotation.value();
		//处理字典翻译
		for (FieldParam fieldParam : fieldParams) {
			Pattern dictPattern = this.getPattern(fieldParam.targetValueField(), fieldParam.targetFieldValueClazz());
			Matcher dictMatcher = dictPattern.matcher(returnJsonResult);
			StringBuffer sb = new StringBuffer();
			//转义字段
			this.translate(fieldParam, dictPattern, dictMatcher, sb);
			dictMatcher.appendTail(sb);
			returnJsonResult = sb.toString();
		}
		result = JSONObject.parseObject(returnJsonResult, returnType);
		//如果这里不返回result，则目标对象实际返回值会被置为null
		//处理完请求时间
		Long endTime = System.currentTimeMillis();
		log.info("The DICT request takes {}ms", endTime - startTime);
		return result;
	}

	/**
	 * 翻译用户id
	 *
	 * @param joinPoint
	 * @return
	 * @throws Throwable
	 */
	@Around("@annotation(com.azxc.rapid.common.aop.anno.TranslationUser)")
	public Object aroundMethodUser(ProceedingJoinPoint joinPoint) throws Throwable {
		//接收到请求时间
		Long startTime = System.currentTimeMillis();
		//注意，如果调用joinPoint.proceed()方法，则修改的参数值不会生效，必须调用joinPoint.proceed(Object[] args)
		Object result = joinPoint.proceed();
		// 第一步、获取返回值类型
		Class returnType = ((MethodSignature) joinPoint.getSignature()).getReturnType();
		//首先，取出要翻译字段的字典值
		String returnJsonResult = JSONObject.toJSONString(result);
		//开始解析（翻译字段注解参数指定的字段）
		Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
		//获取注解上参数
		TranslationUser annotation = method.getAnnotation(TranslationUser.class);
		//处理用户id转名称
		Pattern dictPattern = this.getPattern(annotation.targetValueField(), annotation.targetFieldValueClazz());
		Matcher dictMatcher = dictPattern.matcher(returnJsonResult);
		StringBuffer sb = new StringBuffer();
		//转义字段
		Map<Long, User> userMap = this.getUserMap(dictPattern, dictMatcher);
		dictMatcher.reset();
		this.translate(annotation, dictPattern, dictMatcher, sb, userMap);
		dictMatcher.appendTail(sb);
		returnJsonResult = sb.toString();
		result = JSONObject.parseObject(returnJsonResult, returnType);
		//处理完请求时间
		Long endTime = System.currentTimeMillis();
		log.info("The USER request takes {}ms", endTime - startTime);
		return result;
	}

	/**
	 * 翻译区域id
	 *
	 * @param joinPoint
	 * @return
	 * @throws Throwable
	 */
	@Around("@annotation(com.azxc.rapid.common.aop.anno.TranslationRegion)")
	public Object aroundMethodRegion(ProceedingJoinPoint joinPoint) throws Throwable {
		//接收到请求时间
		Long startTime = System.currentTimeMillis();
		//注意，如果调用joinPoint.proceed()方法，则修改的参数值不会生效，必须调用joinPoint.proceed(Object[] args)
		Object result = joinPoint.proceed();
		// 第一步、获取返回值类型
		Class returnType = ((MethodSignature) joinPoint.getSignature()).getReturnType();
		//首先，取出要翻译字段的字典值
		String returnJsonResult = JSONObject.toJSONString(result);
		//开始解析（翻译字段注解参数指定的字段）
		Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
		//获取注解上参数
		TranslationRegion annotation = method.getAnnotation(TranslationRegion.class);
		//处理区域
		Pattern dictPattern = this.getPattern(annotation.targetValueField(), annotation.targetFieldValueClazz());
		Matcher dictMatcher = dictPattern.matcher(returnJsonResult);
		StringBuffer sb = new StringBuffer();
		//转义字段
		this.translate(annotation, dictPattern, dictMatcher, sb);
		dictMatcher.appendTail(sb);
		returnJsonResult = sb.toString();
		result = JSONObject.parseObject(returnJsonResult, returnType);
		//处理完请求时间
		Long endTime = System.currentTimeMillis();
		log.info("The REGION request takes {}ms", endTime - startTime);
		return result;
	}

	/**
	 * 翻译机构id
	 *
	 * @param joinPoint
	 * @return
	 * @throws Throwable
	 */
	@Around("@annotation(com.azxc.rapid.common.aop.anno.TranslationDept)")
	public Object aroundMethodDept(ProceedingJoinPoint joinPoint) throws Throwable {
		//接收到请求时间
//		Long startTime = System.currentTimeMillis();
		//注意，如果调用joinPoint.proceed()方法，则修改的参数值不会生效，必须调用joinPoint.proceed(Object[] args)
		Object result = joinPoint.proceed();
		// 第一步、获取返回值类型
		Class returnType = ((MethodSignature) joinPoint.getSignature()).getReturnType();
		//首先，取出要翻译字段的字典值
		String returnJsonResult = JSONObject.toJSONString(result);
		//开始解析（翻译字段注解参数指定的字段）
		Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
		//获取注解上参数
		TranslationDept annotation = method.getAnnotation(TranslationDept.class);
		//处理用户id转名称
		Pattern dictPattern = this.getPattern(annotation.targetValueField(), annotation.targetFieldValueClazz());
		Matcher dictMatcher = dictPattern.matcher(returnJsonResult);
		StringBuffer sb = new StringBuffer();
		//转义字段
		this.translate(annotation, dictPattern, dictMatcher, sb);
		dictMatcher.appendTail(sb);
		returnJsonResult = sb.toString();
		result = JSONObject.parseObject(returnJsonResult, returnType);
		//处理完请求时间
//		Long endTime = System.currentTimeMillis();
//		log.info("The request takes {}ms",endTime-startTime);
		return result;
	}


	/**
	 * 机构id 转义成 机构名称
	 *
	 * @param deptAnno
	 * @param fieldPattern
	 * @param fieldMatcher
	 * @param sb
	 */
	private void translate(TranslationDept deptAnno, Pattern fieldPattern, Matcher fieldMatcher, StringBuffer sb) {
		while (fieldMatcher.find()) {
			//取出要翻译字段对应的值
			Matcher dictValueMatcher = fieldPattern.matcher(fieldMatcher.group());
			dictValueMatcher.find();
			String group = dictValueMatcher.group();
			//属性无值
			if (group.split(":").length <= 1) continue;
			String afterName = "";
			//获取被翻译的值
			String beforeValue = group.split(":")[1].replace("\"", "");
			//属性值非为空 为空赋值空串
			if (StringUtils.isNotBlank(beforeValue) && !beforeValue.toLowerCase().equals("null")) {
				afterName = SysCache.getDept(Long.valueOf(beforeValue)).getDeptName();
			}
			StringBuffer buffer = new StringBuffer();
			buffer.append("\"").append(deptAnno.targetNameField()).append("\":\"").append(afterName).append("\",").append(fieldMatcher.group());
			fieldMatcher.appendReplacement(sb, buffer.toString());
		}
	}


	private void translate(TranslationUser userAnno, Pattern fieldPattern, Matcher fieldMatcher, StringBuffer sb, Map<Long, User> map) {
		while (fieldMatcher.find()) {
			//取出要翻译字段对应的值
			Matcher dictValueMatcher = fieldPattern.matcher(fieldMatcher.group());
			dictValueMatcher.find();
			String group = dictValueMatcher.group();
			//属性无值
			if (group.split(":").length <= 1) continue;
			String afterName = "";
			//获取被翻译的值
			String beforeValue = group.split(":")[1].replace("\"", "");
			//属性值非为空 为空赋值空串
			StringBuffer buffer = new StringBuffer();
			if (StringUtils.isNotBlank(beforeValue) && !beforeValue.toLowerCase().equals("null")) {
				User user = map.get(Long.valueOf(beforeValue));
				if (user != null) {
					afterName = user.getRealName();
				}
				if (user != null && userAnno.showPhone()) {
					//是否显示用户的手机号码
					buffer.append("\"").append(userAnno.phoneShowName()).append("\":\"").append(user.getPhone()).append("\",");
				}

				if (user != null && userAnno.showDept()) {
					//是否显示用户所属的机构名称
					String deptIds = user.getDeptId();
					String[] deptArray = deptIds.split(",");
					String deptName = "";
					for (int i = 0; i < deptArray.length; i++) {
						Dept dept = SysCache.getDept(Long.valueOf(deptArray[i]));
						if (i == deptArray.length - 1) {
							deptName = deptName + dept.getDeptName();
						} else {
							deptName = deptName + dept.getDeptName() + ",";
						}
					}
					buffer.append("\"").append(userAnno.deptShowName()).append("\":\"").append(deptName).append("\",");
				}

			}
			buffer.append("\"").append(userAnno.targetNameField()).append("\":\"").append(afterName).append("\",").append(fieldMatcher.group());
			fieldMatcher.appendReplacement(sb, buffer.toString());
		}
	}

	/**
	 * region 转义成 省、市、地区
	 *
	 * @param regionAnno
	 * @param fieldPattern
	 * @param fieldMatcher
	 * @param sb
	 */
	private void translate(TranslationRegion regionAnno, Pattern fieldPattern, Matcher fieldMatcher, StringBuffer sb) {
		//从缓存中一次性取值
		// Map<String, String> dictNames = DictUtil.getDictKeyValueMap(fieldParam.dictType());
		while (fieldMatcher.find()) {
			//取出要翻译字段对应的值
			Matcher dictValueMatcher = fieldPattern.matcher(fieldMatcher.group());
			dictValueMatcher.find();
			String group = dictValueMatcher.group();
			//属性无值
			if (group.split(":").length <= 1) continue;
			//获取被翻译的值
			String beforeValue = group.split(":")[1].replace("\"", "");
			//属性值非为空 为空赋值空串
			String provinceName = "";
			String cityName = "";
			String districtName = "";
			String name = "";
			if (StringUtils.isNotBlank(beforeValue) && !beforeValue.toLowerCase().equals("null")) {
				Region region = RegionCache.getByCode(beforeValue);
				provinceName = region.getProvinceName();
				cityName = region.getCityName();
				districtName = region.getDistrictName();
				name = region.getName();
			}
			String[] targetNameFields = regionAnno.targetNameField();
			StringBuffer buffer = new StringBuffer();
			buffer.append("\"").append(targetNameFields[0]).append("\":\"").append(provinceName).append("\",")
				.append("\"").append(targetNameFields[1]).append("\":\"").append(cityName).append("\",")
				.append("\"").append(targetNameFields[2]).append("\":\"").append(districtName).append("\",")
				.append("\"").append(targetNameFields[3]).append("\":\"").append(name).append("\",")
				.append(fieldMatcher.group());
			fieldMatcher.appendReplacement(sb, buffer.toString());
		}
	}

	/**
	 * 字典值转义为中文
	 *
	 * @param fieldParam
	 * @param fieldPattern
	 * @param fieldMatcher
	 * @param sb
	 */
	private void translate(FieldParam fieldParam, Pattern fieldPattern, Matcher fieldMatcher, StringBuffer sb) {
		//从缓存中一次性取值
		Map<String, String> dictNames = DictUtil.getDictKeyValueMap(fieldParam.dictType());
		while (fieldMatcher.find()) {
			//取出要翻译字段对应的值
			Matcher dictValueMatcher = fieldPattern.matcher(fieldMatcher.group());
			dictValueMatcher.find();
			String group = dictValueMatcher.group();
			//属性无值
			if (group.split(":").length <= 1) continue;
			String dictName = "";
			//获取字典值
			String dictValue = group.split(":")[1].replace("\"", "");
			//属性值非为空 为空赋值空串
			if (StringUtils.isNotBlank(dictValue) && !dictValue.toLowerCase().equals("null")) {
				dictName = dictNames.get(dictValue);
			}
			StringBuffer buffer = new StringBuffer();
			buffer.append("\"").append(fieldParam.targetNameField()).append("\":\"").append(dictName).append("\",").append(fieldMatcher.group());
			fieldMatcher.appendReplacement(sb, buffer.toString());
		}
	}


	/**
	 * 翻译用户多个用户id对应的的信息
	 *
	 * @param joinPoint
	 */
	@Around("@annotation(com.azxc.rapid.common.aop.anno.TranslationUsers)")
	@SneakyThrows
	public Object aroundMethodUsers(ProceedingJoinPoint joinPoint) {
		//接收到请求时间
		Long startTime = System.currentTimeMillis();
		//注意，如果调用joinPoint.proceed()方法，则修改的参数值不会生效，必须调用joinPoint.proceed(Object[] args)
		Object result = joinPoint.proceed();
		// 第一步、获取返回值类型
		Class returnType = ((MethodSignature) joinPoint.getSignature()).getReturnType();
		//首先，取出要翻译字段的字典值
		String returnJsonResult = JSONObject.toJSONString(result);
		//开始解析（翻译字段注解参数指定的字段）
		Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
		//获取注解上参数
		TranslationUsers annotation = method.getAnnotation(TranslationUsers.class);
		//处理用户id转名称
		Pattern dictPattern = this.getPattern(annotation.targetValueField(), annotation.targetFieldValueClazz());
		Matcher dictMatcher = dictPattern.matcher(returnJsonResult);
		StringBuffer sb = new StringBuffer();
		//转义字段
		this.translate(annotation, dictPattern, dictMatcher, sb);
		dictMatcher.appendTail(sb);
		returnJsonResult = sb.toString();
		result = JSONObject.parseObject(returnJsonResult, returnType);
		//处理完请求时间
		Long endTime = System.currentTimeMillis();
		log.info("The USER request takes {}ms", endTime - startTime);
		return result;
	}

	private void translate(TranslationUsers userAnno, Pattern fieldPattern, Matcher fieldMatcher, StringBuffer sb) {
		while (fieldMatcher.find()) {
			//取出要翻译字段对应的值
			Matcher dictValueMatcher = fieldPattern.matcher(fieldMatcher.group());
			dictValueMatcher.find();
			String group = dictValueMatcher.group();
			//属性无值
			if (group.split(":").length <= 1) continue;
			//获取被翻译的值
			String beforeValue = group.split(":")[1].replace("\"", "");
			//属性值非为空 为空赋值空串
			StringBuffer buffer = new StringBuffer();
			if (StringUtils.isNotBlank(beforeValue) && !beforeValue.toLowerCase().equals("null")) {
				List<User> list = UserPlusCache.getUsers(beforeValue);
				if (list != null) {
					buffer.append("\"").append(userAnno.targetNameField()).append("\":");
					List<Map<String, Object>> listJson = new ArrayList<>();
					list.stream().forEach(user -> {
						Map<String, Object> map = new HashMap<>();
						map.put("userId", user.getId());
						map.put("userName", user.getRealName());
						if (userAnno.showDept()) {
							String deptId = user.getDeptId();
							Dept dept = SysCache.getDept(Long.valueOf(deptId));
							map.put("deptName", dept.getDeptName());
						}
						listJson.add(map);
					});
					buffer.append(JSONObject.toJSONString(listJson));
				}
			}
			buffer.append(",").append(fieldMatcher.group());
			fieldMatcher.appendReplacement(sb, buffer.toString());
		}
	}
}
